/**
 * yeahmobi.com Inc.
 * Copyright © 2014 YeahMobi | All Rights Reserved.
 */

package com.ndp.fb.rdb.db.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.ndp.fb.constant.CommonConstants;
import com.ndp.fb.rdb.api.AppInfoRdbService;
import com.ndp.fb.rdb.api.FbUserRdbService;
import com.ndp.fb.rdb.db.DaoTemplate;
import com.ndp.fb.rdb.db.impl.mapper.DefaultRowMapper;
import com.ndp.fb.rdb.model.AppInfo;
import com.ndp.fb.rdb.model.FbUser;
import com.ndp.fb.rdb.model.TokenAndLanguage;
import com.ndp.fb.redis.api.RedisClient;
import com.ndp.fb.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.util.CollectionUtils;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @author giser.yang
 * @Title: FbUserRdbServiceImpl.java
 * @Copyright: Copyright © 2015
 * @Description:
 * @Company: yeahmobi
 * @Created on 下午1:50:28
 */
@Service
public class FbUserRdbServiceImpl extends DaoTemplate implements FbUserRdbService {
    @Autowired
    private RedisClient redisClient;

    @Autowired
    private AppInfoRdbService appInfoRdbService;

    /**
     * @param fbUserId
     * @return
     * @discription
     * @author giser.yang
     * 创建时间 2015年6月3日 下午1:51:55
     * @see com.ndp.fb.rdb.api.FbUserRdbService#getFbUserByFbUserId(java.lang.Long)
     */

    @Override
    public FbUser getFbUserByFbUserId(Long fbUserId) {
        String sql = "SELECT * FROM fb_user WHERE fb_user_id=?";
        return findOne(sql, new Object[]{fbUserId}, DefaultRowMapper.autoRowMapper(FbUser.class));
    }

    @Override
    public String getTokenByFbUserId(Long fbUserId) {
        String sql = "SELECT * FROM fb_user WHERE  is_invalid=0 and fb_user_id=?";
        FbUser fbUser = findOne(sql, new Object[]{fbUserId}, DefaultRowMapper.autoRowMapper(FbUser.class));
        if ((fbUser == null) || (StringUtil.isEmpty(fbUser.getAccessToken()))) {
            return null;
        }
        return fbUser.getAccessToken();
    }

    @Override
    public String getTokenByUserId(String userId) {
        String sql = "SELECT * FROM fb_user WHERE  is_invalid=0 and user_id=?";
        FbUser fbUser = findOne(sql, new Object[]{userId}, DefaultRowMapper.autoRowMapper(FbUser.class));
        if ((fbUser == null) || (StringUtil.isEmpty(fbUser.getAccessToken()))) {
            return null;
        }
        return fbUser.getAccessToken();
    }

    @Override
    public TokenAndLanguage getTokenAndLanguageByUserId(String userId) {
        String sql = "SELECT f.access_token,u.language FROM fb_user f, user u WHERE u.ticket = f.user_id and f.user_id=?";
        return findOne(sql, new Object[]{userId}, DefaultRowMapper.autoRowMapper(TokenAndLanguage.class));
    }

    @Override
    public String getTokenByBmId(Long bmId) {
        String sql = "SELECT f.* FROM fb_user f JOIN fb_user_business_manager b ON f.fb_user_id = b.fb_user_id  WHERE f.is_invalid=0 AND b.fb_business_id=? AND b.role = 'ADMIN' ";
        FbUser fbUser = findOne(sql, new Object[]{bmId}, DefaultRowMapper.autoRowMapper(FbUser.class));
        if ((fbUser == null) || (StringUtil.isEmpty(fbUser.getAccessToken()))) {
            return null;
        }
        return fbUser.getAccessToken();
    }

    /**
     * @param userId
     * @return
     * @discription
     * @author giser.yang
     * 创建时间 2015年6月3日 下午1:51:55
     * @see com.ndp.fb.rdb.api.FbUserRdbService#getFbUserByUserId(java.lang.String)
     */

    @Override
    public FbUser getFbUserByUserId(String userId) {
        String sql = "SELECT * FROM fb_user WHERE user_id=?";
        return findOne(sql, new Object[]{userId}, DefaultRowMapper.autoRowMapper(FbUser.class));
    }

    /**
     * @return
     * @discription
     * @author giser.yang
     * 创建时间 2015年6月3日 下午2:41:34
     * @see com.ndp.fb.rdb.api.FbUserRdbService#getAllFbUser()
     */

    @Override
    public List<FbUser> getAllFbUser() {
        String sql = "SELECT * FROM fb_user";
        return getJdbcTemplate().query(sql, DefaultRowMapper.autoRowMapper(FbUser.class));
    }

    /**
     * @param fbUser
     * @return
     * @discription
     * @author giser.yang
     * 创建时间 2015年6月6日 下午2:14:13
     * @see com.ndp.fb.rdb.api.FbUserRdbService#saveFbUser(com.ndp.fb.rdb.model.FbUser)
     */

    @Override
    public Long saveFbUser(final FbUser fbUser) {
        return saveResultId(fbUser);
    }

    /**
     * @param fbUser
     * @return
     * @discription
     * @author giser.yang
     * 创建时间 2015年6月6日 下午2:14:13
     * @see com.ndp.fb.rdb.api.FbUserRdbService#updateFbUser(com.ndp.fb.rdb.model.FbUser)
     */

    @Override
    public Integer updateFbUser(final FbUser fbUser) {
        return getJdbcTemplate().update(new PreparedStatementCreator() {
            public PreparedStatement createPreparedStatement(Connection con)
                    throws SQLException {
                String sql = "UPDATE fb_user SET "
                        + "email = ?,first_name = ?,gender = ?,last_name = ?,link = ?,locale = ?,name = ?,timeZone = ?,updated_time = ?,user_id = ?,verified = ?,access_token=?,is_invalid=? where fb_user_id = ?";
                PreparedStatement ps = con.prepareStatement(sql);

                ps.setObject(1, fbUser.getEmail());
                ps.setObject(2, fbUser.getFirstName());
                ps.setObject(3, fbUser.getGender());
                ps.setObject(4, fbUser.getLastName());
                ps.setObject(5, fbUser.getLink());
                ps.setObject(6, fbUser.getLocale());
                ps.setObject(7, fbUser.getName());
                ps.setObject(8, fbUser.getTimeZone());
                ps.setObject(9, fbUser.getUpdatedTime());
                ps.setObject(10, fbUser.getUserId());
                ps.setObject(11, fbUser.getVerified());
                ps.setObject(12, fbUser.getAccessToken());
                ps.setObject(13, fbUser.getIsInvalid());
                ps.setObject(14, fbUser.getFbUserId());
                return ps;
            }
        });
    }

    /**
     * @param fbUserId
     * @return
     * @discription
     * @author giser.yang
     * 创建时间 2015年6月19日 下午1:26:58
     * @see com.ndp.fb.rdb.api.FbUserRdbService#getFbUserFromCache(java.lang.Long)
     */

    @Override
    public FbUser getFbUserFromCache(Long fbUserId) {
        FbUser fbUser = (FbUser) redisClient.get("FBUSER" + fbUserId);
        if (fbUser == null) {
            fbUser = this.getFbUserByFbUserId(fbUserId);
            redisClient.set("FBUSER" + fbUserId, fbUser);
        }
        return fbUser;
    }



    /**
     * 查询本公司下面的所有管理员的fbuser
     *
     * @param userId
     * @return
     */
    public List<FbUser> getAdminFbUserByUserId(String userId) {
        String sql = "SELECT\n" +
                "	fuser.*\n" +
                "FROM\n" +
                "	fb_user fuser,\n" +
                "	user u,\n" +
                "	user u1\n" +
                "WHERE\n" +
                "	u.ticket = fuser.user_id\n" +
                "AND u.org_id = u1.org_id\n" +
                "AND u.role_id = 1\n" +
                "AND u1.ticket = ?";
        return getJdbcTemplate().query(sql, new Object[]{userId}, DefaultRowMapper.autoRowMapper(FbUser.class));
    }

    @Override
    public Boolean getIsInvalidByUserId(String userId) {
        String sql = "SELECT is_invalid from fb_user where user_id=?";
        return this.queryIsInvalid(sql, userId);
    }


    @Override
    public Boolean getIsInvalidByAcessToken(String accessToken) {
        String sql = "SELECT is_invalid from fb_user  where access_token=?";
        return this.queryIsInvalid(sql, accessToken + "");
    }


    @Override
    public int updateInValidByAcessToken(final String accessToken, final String isValid) {
        return getJdbcTemplate().update(new PreparedStatementCreator() {
            public PreparedStatement createPreparedStatement(Connection con)
                    throws SQLException {
                String sql = "UPDATE fb_user SET "
                        + "is_invalid  = ? where access_token = ?";
                PreparedStatement ps = con.prepareStatement(sql);

                ps.setObject(1, isValid);
                ps.setObject(2, accessToken);
                return ps;
            }
        });
    }

    /**
     * 清除 redis 中的失效标识
     *
     * @param fbUser
     */
    public void clearValidByFbUser(FbUser fbUser) {
        String preFix = "IsInvalid_";
        String accessTokenKey = preFix + fbUser.getAccessToken();
        String fbUserIdKey = preFix + fbUser.getFbUserId();
        String userIdKey = preFix + fbUser.getUserId();
        deleteRedisKey(accessTokenKey);
        deleteRedisKey(fbUserIdKey);
        deleteRedisKey(userIdKey);
    }

    private void deleteRedisKey(String key){
        if (this.redisClient.hasKey(key)) {
            this.redisClient.delete(key);
        }
    }

    @Override
    public void clearValidByFbAccessToken(String accessToken) {
        String sql = "SELECT * from fb_user  where access_token=?";
        FbUser fbUser = findOne(sql, new Object[]{accessToken}, DefaultRowMapper.autoRowMapper(FbUser.class));
        this.clearValidByFbUser(fbUser);
    }


    private boolean queryIsInvalid(String sql, String id) {
        String key = "IsInvalid_" + id;
        String appInfoKey = CommonConstants.APPINFO_KEY;

        if (!redisClient.hasKey(appInfoKey)) {//将appinfo信息存入到缓存中
            AppInfo appInfo = appInfoRdbService.getAppInfo();
            this.redisClient.set(appInfoKey, appInfo, 1, TimeUnit.DAYS.toString());
        }

        //todo 这里有问题，
        if (this.redisClient.hasKey(key)) {
            Object isInvalidObj = this.redisClient.get(key);
            if (isInvalidObj != null) {
                Boolean isInvalid = (Boolean) isInvalidObj;
                return isInvalid;
            } else {
                return this.getIsInvalid(key, sql, id);
            }
        } else {
            return this.getIsInvalid(key, sql, id);
        }
    }


    private boolean getIsInvalid(String key, String sql, String id) {
        boolean isInvalid = false;
        try {
            int isInvalidInt = 0;
            List<Map<String, Object>> list = this.getJdbcTemplate().queryForList(sql, id);
            if (!CollectionUtils.isEmpty(list)) {
                Map data = list.get(0);
                if (data != null) {
                    Object o = data.get("is_invalid");
                    if (o != null) {
                        isInvalidInt = Integer.parseInt(o.toString());
                    }
                }
            }
            isInvalid = isInvalidInt != 0;
            this.redisClient.set(key, isInvalid, 1, TimeUnit.DAYS.toString());
        } catch (Exception e) {
            isInvalid = false;
            logger.error(e.getMessage(), e);
        }
        return isInvalid;
    }


    @Override
    public void deleteFbUser(Long fbUserId) {
        String sql = "DELETE FROM fb_user  where fb_user_id = ?";
        getJdbcTemplate().update(sql, new Object[]{fbUserId});
    }
}
